/*
 * Copyright Aristool AG Switzerland
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package org.opprua.tidy.gens;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.opprua.tidy.util.CodePrint;

/**
 * TODO: add Java doc
 *
 * Prepared for first commit: 15.04.2007
 *
 * @author Lin Li
 */
public class GCall extends Gtor {

  private String object = "";
  private String method = "";
  private List<String> params = new ArrayList<String>();
  private String returnType = "";
  private String res = "";

  /**
   * <p>
   * Start the generation of a call to the object and method.
   * </p>
   * 
   * @param objectName
   *          owner of the method (class or object)
   * @param methodName
   *          the method name
   */
  public GCall(String objectName, String methodName) {
    object = objectName;
    method = methodName;
  }

  /**
   * <p>
   * Add a call parameter, this parameter is added literally.
   * </p>
   * 
   * @param param
   *          the parameter in java literal
   * @return this, for chained call
   */
  public GCall param(String param) {
    params.add(param);
    return this;
  }

  /**
   * <p>
   * Add a call parameter, this parameter is quotted as a string.
   * </p>
   * 
   * @param param
   *          the parameter in java string
   * @return this, for chained call
   */
  public GCall stringParam(String param) {
    params.add("\"" + param + "\"");
    return this;
  }

  /**
   * <p>
   * Assign the call result to a variable in the generated code.
   * </p>
   * 
   * @param type
   *          the of the variable as in an assignment declaration, can be null
   *          or empty if the variable is already declared in the generated
   *          code.
   * @param res
   *          the name of the variable in the generated code
   * @return this, for chained calls.
   */
  public GCall assignTo(String type, String res) {
    returnType = type.trim();
    this.res = res.trim();
    return this;
  }

  /**
   * <p>
   * Get the formated string for this call directly.
   * </p>
   * 
   * @return the formated string.
   */
  public String getString() {
    int length = 0;

    for (Iterator<String> iter = params.iterator(); iter.hasNext();) {
      length += ((String) iter.next()).length();
    }

    String head = object + "." + method;
    if (res.length() > 0) {
      if (returnType.length() > 0) {
        head = returnType + " " + res + " = " + head;
      } else {
        head = res + " = " + head;
      }
    }

    StringBuffer buf = new StringBuffer(head);
    buf.append("(");
    boolean multi = false;
    if (head.length() + length > 60 && params.size() > 2) {
      multi = true;
    }
    for (int i = 0; i < params.size(); i++) {
      if (i > 0) {
        buf.append(",");
      }
      if (multi) {
        buf.append("\n          ");
      }
      buf.append((String) params.get(i));
    }
    buf.append(")");

    return buf.toString();
  }

  /**
   * <p>
   * Dump to a writer
   * </p>
   */
  public void dump(CodePrint w) {
    w.print(getString());
    w.println(";");
  }
}
